<template>
    <cmDialog v-model="visible" :modalTitle="modaltitle + '  权限配置'" modelWidth="600px">
        <!-- <div style="min-height: 400px;overflow: auto;"> -->
            <div class="form-label">已选择的权限：</div>
            <div class="tag-content">
                <el-tag
                    v-for="tag in tags"
                    :key="tag.id"
                    class="mx-1 mx-tag"
                    closable
                    @close="handleClose(tag)"
                >
                    {{ tag.label }}
                </el-tag>
            </div>
            <div class="select-all"><el-checkbox :indeterminate="isIndeterminate" v-model="checked1" @change="selectAll">全选</el-checkbox></div>
            <div class="tree-content">
                <el-tree
                    ref="treeTemplate"
                    show-checkbox
                    :data="menuList"
                    node-key="id"
                    :default-expand-all="true"
                    :render-after-expand="false"
                    :render-content="renderContent"
                    style="width: 100%"
                    clearable
                    @check-change="handleCheckChange"
                />
            </div>
            <div class="dialog-foot">
                <el-button type="primary" @click="handleAddFormSubmit">保存</el-button>
            </div>
        <!-- </div> -->
    </cmDialog>
</template>
<script lang="ts" setup>
import cmDialog from '@/components/cm-dialog/index.vue'
import { ref, reactive, computed, onMounted, watch, nextTick } from 'vue'
import { ElTree, ElMessage, ElIcon } from 'element-plus'
import { Document, Aim } from '@element-plus/icons-vue';

import { useUserInfoApi } from '@/api/sys/user'
import { queryMenuSelected, roleMenuSubmitApi } from '@/api/system/rbac'

import type Node from 'element-plus/es/components/tree/src/model/node'

const visible = ref(false)
const menuList = ref([]) // 所有的菜单
const checked1 = ref(false)
const isIndeterminate = ref(false)
const allIds = ref(0)

const roleCode = ref()
const modaltitle = ref("权限配置")

const treeTemplate = ref<InstanceType<typeof ElTree>>()

const emit = defineEmits(['refreshDataList'])

const tags = computed(()=>{
    return treeTemplate.value?.getCheckedNodes(false, false)
})

const init = (isUpdate: boolean, row: any) => {
	visible.value = true
    roleCode.value = row.roleCode
    
    if(isUpdate) { // isUpdate  true-新增  、false-编辑row有数据 反显
        // 重置画面数据
        // tags.value = []
    }
    modaltitle.value = row.roleName
	// 权限菜单详情
    roleDetailMethod(row)
}
 
interface paramObject {
    roleCode?: string
}
interface saveObject {
    menuIds?: Object,
    roleCode?: string 
}
// 通过id找到对应的node
const findNodeById = (nodes, targetId) => {
    for (const node of nodes) {
      if (node.id === targetId) {
        return node
      } else if (node.children && node.children.length > 0) {
        const found = findNodeById(node.children, targetId)
        if (found) {
          return found
        }
      }
    }
    return null; // 如果未找到，返回 null
  }
// 通过指定的node、返回所有子节点(包括孙子节点等)
const getAllChildren = (node) => {
    let children = []
    if (node && node.children && node.children.length > 0) {
      for (const child of node.children) {
        children.push(child.id)
        children = children.concat(getAllChildren(child))
      }
    }
    return children // 返回所有子节点数组(包括孙子节点等)
}

// 数组对比，判断节点是否都在；
// true (父亲id保留)、false 说明不是全选(去掉父亲id)
const allElementsInArray = (arr1, arr2) => {
    return arr1.every(item => arr2.includes(item));
}
const menuIdsSelect = (allList, checkList) => {
    var delIds = []
    var targetId
    var allChildren = []
    var linshi = [...checkList];
    
    checkList.forEach(element => {
        targetId = element
        var foundNode = findNodeById(allList, targetId)
        if (foundNode) {
            allChildren = getAllChildren(foundNode)
            // console.log('All children:', allChildren)
            if (!allElementsInArray(allChildren, linshi)) {
                delIds.push(targetId)
            }
        } else {
            // console.log('Node not found'); // 如果未找到节点，打印提示信息。
        }
    })
    // console.log("删除的父亲：", delIds)
    const result = linshi.filter(item => !delIds.includes(item))
    treeTemplate.value!.setCheckedKeys(result, false)
}

// 权限菜单详情
const roleDetailMethod = async (data: paramObject) => {
    let queryParam = {
        roleCode: data.roleCode
    }
	await queryMenuSelected(queryParam).then(res => {
        menuList.value = res.data.systemMenuList
        // treeTemplate.value!.setCheckedKeys(res.data.menuIds, false)
        // console.log("后端已选择的：", res.data.menuIds)
        // console.log("所有的menu：",res.data.systemMenuList)
        menuIdsSelect(res.data.systemMenuList, res.data.menuIds)
        
        if(res.data.menuIds.length > 0) {
            isIndeterminate.value = true
        }
	})
    allIds.value = getNodeKeyIds(menuList.value, []).length
    // console.log("所有菜单的ids：", getNodeKeyIds(menuList.value, []).length)
}

const getNodeKeyIds = (tree: any, result: Number[]) => {
    if (!Array.isArray(tree)) return []; // 如果不是一个数组，则返回
    for (let i = 0; i < tree.length; i++) {
        let node = tree[i];
        result.push(node.id);
        if (Array.isArray(node.children)) {
            getNodeKeyIds(node.children, result);
        }
    }
    return result;
}

// 点击树节点事件处理
// const handleCheckChange = (data: Object) => {
//     // console.log(data)
//     const newArr = tags.value
//     let index = newArr.findIndex((item) => item.name === data.label);
//     // console.log(index)
//     if (index !== -1) {
//         newArr.splice(index, 1);
//     } else {
//         newArr.push({ name: data.label, id: data.id, label: data.label});
//     }
// }
interface CheckData {
    label: string;
    id: string | number;
}

const handleCheckChange = (data: CheckData) => {
    let checkedNodes = treeTemplate.value!.getCheckedNodes()
    isIndeterminate.value = checkedNodes.length > 0 && checkedNodes.length < allIds.value // 有数据，但不是all
    if(checkedNodes.length == allIds.value) { // all
        checked1.value = true
    } else if(checkedNodes.length == 0) {
        isIndeterminate.value = false
    }
    // console.log('========:', tags.value)
    // console.log("当前点击的节点", treeTemplate.value!.getCheckedNodes())
    // console.log(treeTemplate.value!.getCheckedKeys(false))
    // console.log(data)
    // if (!Array.isArray(tags.value)) return; // 确保 tags.value 是数组
    // const newArr = tags.value;
    // let index = newArr.findIndex((item) => item.name === data.label);
    // // console.log(index)
    // if (index !== -1) {
    //     newArr.splice(index, 1);
    // } else {
    //     newArr.push({ name: data.label, id: data.id, label: data.label });
    // }
};


const handleClose = (tag: any) => {
    // console.log('closetag', tag.id)
    if (!Array.isArray(tags.value)) return; // 确保 tags.value 是数组
    for (let i = 0; i < tags.value.length; i++) {
        const element = tags.value[i];
        if (tag.id === element.id) {
            tags.value.splice(i, 1);
            treeTemplate.value!.setChecked(tag.id, false, true);
            isIndeterminate.value = true // 一旦进行了删除就半开
        }
      }
}

// 更新角色
const handleAddFormSubmit = async () => {
    var obj: saveObject = Object.create(null)
    obj.roleCode = roleCode.value
   // obj.menuIds = treeTemplate.value?.getCheckedKeys(false)
    // console.log("得到选中的key", treeTemplate.value?.getCheckedKeys(false))
    // console.log("连带父亲：", treeTemplate.value?.getHalfCheckedKeys())
    obj.menuIds = [...treeTemplate.value?.getCheckedKeys(false), ...treeTemplate.value?.getHalfCheckedKeys()];
	await roleMenuSubmitApi(obj).then(res => {
    
        ElMessage.success({
            message: '操作成功',
            duration: 500,
            onClose: () => {
                visible.value = false
                emit('refreshDataList')
            }
        })
    
	})
}
// tree 显示
interface Tree {
  id: number
  label: string
  children?: Tree[],
  menuType: string | Number
}
const renderContent = (
  h: any,
  {
    node,
    data,
    store,
  }: {
    node: Node
    data: Tree
    store: Node['store']
  }
) => {
    if (data.menuType == 1) {
        return h('span', {}, [node.label, h(Document, {style: {width: '15px', position: 'relative', top: '3px'}}, {})]);
        // return h('span', null, node.label, h(ElIcon, null, '', h(Document, null, '')))
    } else {
        // return h('span', null, node.label, h(ElIcon, null, '', h(Aim, null, null)))
        return h('span', null, node.label)
    }
}
// 全部选择 或者 取消全选
const selectAll = (val: boolean) => {
    // isIndeterminate.value = false
    if(checked1.value) {
        if (treeTemplate.value) {
            treeTemplate.value.setCheckedNodes(menuList.value);
        }
    } else {
        Object.assign(tags.value, [])
        if (treeTemplate.value) {
            treeTemplate.value.setCheckedNodes([]);
        }
    }
}
defineExpose({
	init
})

</script>
<style scoped>
.dialog-foot {
    text-align: center;
}

.select-all {
    border-top: 1px solid #eee;
    margin-top: 8px;
}

.tree-content {
    max-height: 290px;
    /* margin-top: 5px; */
    overflow: auto;
}

.tag-content {
    max-height: 200px;
    overflow-y: auto;
}

.form-label {
    padding-bottom: 5px;
}

.mx-tag {
    margin-left: 5px;
    margin-right: 5px;
    margin-bottom: 5px;
}
</style>
<style>
.custon-body {
    max-height: none !important;
    overflow: unset !important;
}
</style>